8.2 - Using Harmony
The default Mod Template automatically generates a comment to enable any Harmony Patches in your code.
public class ExampleMod : SonsMod
{
public ExampleMod()
{
// Uncomment any of these if you need a method to run on a specific update loop.
//OnUpdateCallback = MyUpdateMethod;
//OnLateUpdateCallback = MyLateUpdateMethod;
//OnFixedUpdateCallback = MyFixedUpdateMethod;
//OnGUICallback = MyGUIMethod;
// Uncomment this to automatically apply harmony patches in your assembly.
HarmonyPatchAll = true;
}
}
Creating a basic Harmony Patch
A Harmony patch requires a few things to work:
- The class you want to patch
- The name of the method you want to patch
- The Harmony method
//Enter Cave
[HarmonyPatch(typeof(CaveEntranceManager), "OnCaveEnter")]
private static class OnCaveEnterPatch
{
private static void Prefix()
{
//Your code here
}
}
In this example we create a patch for the class "CaveEntrancemanager" and the method "OnCaveEnter".
This specific method is called when the player enters any cave.
It is defined as a Prefix patch, meaning it will run before the original method.
The name of the Harmony method can be anything you want, but it is required to be unique.
Additionall all Harmony patches must be static.
//Exit Cave
[HarmonyPatch(typeof(CaveEntranceManager), "OnCaveExit")]
private static class OnCaveExitPatch
{
private static void Postfix()
{
//Your code here
}
}
Here we create another patch for the class "CaveEntranceManager" but this time on the method "OnCaveExit".
This specific method is called when the player exits any cave.
It is defined as a Postfix patch, meaning it will run after the original method.
In this case a prefix might be the better choice, as we allow the game to finish whatever it is doing before executing our code.
Advanced usage of patches
You can also use a Prefix or Postfix to change the result of a method.
For this example we will patch this method:
public class ExampleClass
{
public bool GetExampleBool()
{
return true;
}
}
We can create a patch to change the result of the method "GetExampleBool" to false.
[HarmonyPatch(typeof(ExampleClass), "GetExampleBool")]
private static class SetExampleToFalsePatch
{
private static void Postfix(ref bool __result)
{
__result = false;
}
}
With this patch the method will now always return false instead of true.
This can both be done as a prefix and as a postfix. When a result is set with a harmony patch it will always be the final result of the method.
In some cases you might also want to prevent the original method from running at all.
This can be achieved by using a prefix and returning false, as seen here:
[HarmonyPatch(typeof(ExampleClass), "GetExampleBool")]
private static class SetExampleToFalsePatch
{
private static bool Prefix(ref bool __result)
{
__result = false;
return false; //This will prevent the original method from running, returning true would still allow the original method to run
}
}
Skipping a method does have other side effects as well.
The first prefix that skips the method will also skip all remaining prefixes on the same method.
But any postfixes will still execute.
Accessing Arguments
You can also access the arguments of the original method.
For this we will create another example:
public class ExampleClass
{
public int AmountOfCookies(string cookieType, int jarSize)
{
if(cookieType == "chocolate")
{
return jarSize * 2;
}
else
{
return jarSize * 5;
}
}
}
We will now create a patch that will double the amount of cookies if the cookie type is "chocolate".
We will also prevent the original method from executing, so only our code will run.
[HarmonyPatch(typeof(ExampleClass), "AmountOfCookies")]
private static class AmountOfCookiesPatch
{
private static bool Prefix(ref int __result, string cookieType, int jarSize)
{
if(cookieType == "chocolate")
{
__result = jarSize * 4; //We need to set the result, we cannot return it
}
else
{
__ result = jarSize * 5;
}
return false; //Do not execute the original method
}
}